package top.lshaci.framework.log.aspect;

import cn.hutool.log.LogFactory;
import lombok.AllArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import top.lshaci.framework.log.annotation.Log;
import top.lshaci.framework.log.enums.OperateStatus;
import top.lshaci.framework.log.model.LogModel;
import top.lshaci.framework.log.service.LogService;
import top.lshaci.framework.log.thread.LogThreadLocal;

import java.lang.reflect.Method;

/**
 * LogAspect
 *
 * @author lshaci
 * @since 1.0.9
 */
@Aspect
@Order(2)
@AllArgsConstructor
public class LogAspect {

    private static final cn.hutool.log.Log logger = LogFactory.get(LogAspect.class);

    private final LogService logService;

    /**
     * 切入点进行日志操作
     *
     * @param joinPoint 切入点信息
     * @param log       日志标题
     * @throws Throwable 目标方法抛出的异常
     */
    @Around("@annotation(log)")
    public void around(ProceedingJoinPoint joinPoint, Log log) throws Throwable {
        OperateStatus status = null;
        String exceptionMessage = null;
        try {
            joinPoint.proceed();
            status = OperateStatus.success;
        } catch (Throwable e) {
            status = OperateStatus.failure;
            exceptionMessage = e.getMessage();
            throw e;
        } finally {
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            Method targetMethod = methodSignature.getMethod();
            Object content = LogThreadLocal.get(Object.class);
            LogModel logModel = new LogModel()
                    .setTargetClass(targetMethod.getDeclaringClass())
                    .setTargetMethod(targetMethod.getName()).setArgs(joinPoint.getArgs())
                    .setStatus(status).setTitle(log.value()).setContent(content)
                    .setExceptionMessage(exceptionMessage);
            try {
                logService.record(logModel);
            } catch (Exception e) {
                logger.error(e, "记录日志失败");
            } finally {
                LogThreadLocal.remove();
            }
        }
    }
}
